package com.ruoyi.basis.utils.minio;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.mashuai.utils.base.MsAssertUtils;
import com.mashuai.utils.base.MsEmptyUtils;
import com.mashuai.utils.toolkit.core.msConverts.MsTimeUtils;
import com.ruoyi.basis.config.MinioConfig;
import com.ruoyi.basis.utils.minio.dto.MinioUploadDto;
import com.ruoyi.common.utils.file.FileUploadUtils;
import io.minio.BucketExistsArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.messages.Bucket;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * minio工具类
 *
 * @ClassName: MinioUtils
 * @Author : mashuai
 * @Description: TODO
 */
@Slf4j
public class MinioUtils {

    /***
     * 上传文件
     * @param file 文件
     * @param bizId 此次文件上传的业务id
     * @return:
     * @author:mashuai
     */
    public static MinioUploadDto upload(MultipartFile file, String bizId) throws Exception {
        //获取文件存储桶名
        InputStream inputStream = file.getInputStream();
        String bucketName = getBucketName(file);
        //FileUploadUtils.getExtension

        String originalFilename = file.getOriginalFilename();
        //新的文件名字
        String fileName = getFileOnlyNamePath(bizId, originalFilename);
        //上传到minio
        getMinioClient().putObject(PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(inputStream, inputStream.available(), -1).contentType(file.getContentType()).build());
        //访问路径
        String relativePath = "/" + bucketName + "/" + fileName;
        //访问地址
        String viewUrl = MinioConfig.getUrl() + relativePath;
        //关闭流
        inputStream.close();
        MinioUploadDto dto = new MinioUploadDto(viewUrl, relativePath, fileName, originalFilename);
        return dto;
//        log.info("上传文件访问地址：{}", viewUrl);
////        //插入上传记录
//        SysFileEntity entity = new SysFileEntity();
//        entity.setCreateTime(new Date());
//        entity.setCreateBy(SecurityUtils.getUsername());
//        entity.setBizId(bizId);
//        entity.setName(originalFilename);
//        entity.setSuffix(suffix);
//        entity.setViewUrl(viewUrl);
//        entity.setSize(file.getSize());
//        entity.setSizeUnit(formatSize(file));
//        MsDb.save(entity);


    }


    /**
     * 获取文件上传的路径
     **/
    private static String getFileOnlyNamePath(String bizId, String fileName) {
        // 加一个/表示创建一个文件夹，以年月日为上传文件组，比如20240202/文件名称321312312.jpg
        if (MsEmptyUtils.isEmpty(bizId)) {
            bizId = IdWorker.getIdStr();
        }
        String ymdTime = MsTimeUtils.getTimeNowStr(MsTimeUtils.sdfYmd).replaceAll("-", "");
        return ymdTime + "/" + bizId + "_" + fileName;
    }

    /**
     * 获取文件上传的桶名称
     **/
    private static String getBucketName(MultipartFile file) {
        //获取文件后缀，然后分别丢进不同的桶中
        String suffix = getFileNameSuffix(file);
        //todo 判断存放在哪个通中
        return MinioConfig.getDefBucketName();
    }

    /***
     * 获取minio对象
     * */
    private static MinioClient getMinioClient() {
        return MinioConfig.getMinioClient();
    }


    /**
     * 判断Bucket是否存在，true：存在，false：不存在
     */
    @SneakyThrows(Exception.class)
    private static boolean bucketExists(String bucketName) {
        return getMinioClient().bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
    }

    /**
     * 列出所有存储桶名称
     */
    @SneakyThrows
    public static List<String> listBucketNames() {
        List<Bucket> bucketList = listBuckets();
        List<String> bucketListName = new ArrayList<>();
        for (Bucket bucket : bucketList) {
            bucketListName.add(bucket.name());
        }
        return bucketListName;
    }

    /**
     * 列出所有存储桶
     */
    @SneakyThrows
    public static List<Bucket> listBuckets() {
        return getMinioClient().listBuckets();
    }


    /**
     * 获取文件名后缀
     */
    private static String getFileNameSuffix(MultipartFile file) {
        String fileName = file.getOriginalFilename();
        if (!fileName.contains(".")) {
            //尝试从流中获取文件后缀
            String extension = FileUploadUtils.getExtension(file);
            if (MsEmptyUtils.isEmpty(extension)) {
                MsAssertUtils.throwException("文件名：" + fileName + "，无法解析到文件后缀");
            }
            return extension;
        }
        String[] fileNameArray = file.getOriginalFilename().split("\\.");
        return fileNameArray[fileNameArray.length - 1];
    }

    /***
     * 格式化文件大小
     * **/
    private static String formatSize(MultipartFile file) {
        long size = file.getSize();
        final String[] units = {"bytes", "KB", "MB", "GB", "TB"};
        int unitIndex = 0;
        double sizeInUnit = size;
        while (sizeInUnit > 1024 && unitIndex < units.length - 1) {
            sizeInUnit /= 1024;
            unitIndex++;
        }
        return String.format("%.2f %s", sizeInUnit, units[unitIndex]);
    }
}
